﻿using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;


namespace DailyFx.UI
{

	public interface IMenuManager :  IPartImportsSatisfiedNotification
	{
		/// <summary>
		///		Children 
		/// </summary>
		IBindableCollection<IMenu> Children { get; }


		// anything missed ?? 
	}

	public class MenuManager : IMenuManager
	{
		// children part .
		private IBindableCollection<IMenu> children = new BindableCollection<IMenu>();


		protected MenuManager ()
		{
			var props = typeof(IMenuMetadata).GetProperties();

		}

		[ImportMany]
		protected Lazy<IMenu, IMenuMetadata>[] _children
		{
			get;
			set;
		}

		public IBindableCollection<IMenu> Children
		{
			get { return children; }
		}



		protected virtual void Sort ()
		{
			var plain = _children.Select (
				(c) =>
				{
					return new CItem()
					{
						Root = c.Metadata.MenuRoot,
						Prev = c.Metadata.MenuPrev,
						Next = c.Metadata.MenuNext,

						Value = c.Value
					};
				}).ToList();

			var roots = Register ( plain.Where(i => string.IsNullOrEmpty(i.Root)).ToList() );

			foreach (var item in plain)
			{
				var root = plain.FirstOrDefault( i => string.Equals(i.Value.KeyText, item.Root) );
				if (root != null)
				{
					root.Children.Add( item);
				}
			}

			foreach (var item in roots)
			{
				_Sort ( item);
			}

			Children.AddRange ( roots.Select(it => it.Value) );
		}

		private void _Sort ( CItem item )
		{
			if (item.Children.Count == 0)
			{
				return;
			}

			// 1. Child Recursion.
			foreach (var i in item.Children)
			{
				_Sort( i);
			}

			// 2. Sort
			var sc = Register( item.Children);
			foreach ( var c in sc )
			{
				IMenu parent = item.Value as IMenu ;
				if ( parent != null )
				{
					parent.Children.Add ( c.Value);
				}
			}
		}

		private List<CItem> Register( List<CItem> items)
		{
			//1. Sort
			var result = new List<CItem>();
			var cache = new List<CItem>();

			foreach (var i in items)
			{
				if ( string.IsNullOrEmpty( i.Prev) && string.IsNullOrEmpty(i.Next))
				{
					result.Add(i);
				}
				else
				{
					cache.Add(i);
				}
			}

			while (cache.Count > 0)
			{
				List<CItem> cache2 = new List<CItem> ();
				
				int n = cache.Count;
				foreach (var c in cache )
				{
					if (!string.IsNullOrEmpty( c.Next))
					{
						var prev = result.FirstOrDefault( x => x.Value.KeyText == c.Next);
						if (prev != null)
						{
							result.Insert( result.IndexOf(prev), c);
						}
						else
						{
							cache2.Add( c);
						}
					}
					else
					{
						var next = result.FirstOrDefault( x => x.Value.	KeyText == c.Prev);
						if (next != null)
						{
							int index = result.IndexOf( next);
							if (index == result.Count - 1)
							{
								result.Add( c);
							}
							else
							{
								result.Insert( index + 1, c);
							}
						}
						else
						{
							cache2.Add( c);
						}
					}
				}

				if ( n == cache2.Count )
				{
					result.Add( cache2[0] );
					cache2.RemoveAt( 0);
				}

				cache = cache2;
			}

			//2. Notify IUIPart already hosted by this manager .
			// todo:
			// result.Apply( o => o.Value.OnHosted() );

			return result;
		}


		protected virtual void _Sink()
		{
			if (_children == null || _children.Length == 0)
				return;

			children.Clear();
			//Sort children according to attribute metadata's property .
			Sort();
		}
	

		//
		public void OnImportsSatisfied()
		{
			_Sink ();
		}


		/// <summary>
		///		Linked ...
		/// </summary>
		private class CItem 
		{
			//
			private List<CItem> children = new List<CItem>();

			public string Root { get; set; }
			public string Prev { get; set; }
			public string Next { get; set; }

			public IMenu Value { get; set; }

			public List< CItem > Children
			{
				get { return children; }
			}
		}


	}
}
